home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pnl005.zip / PNL005.TXT < prev    next >
Text File  |  1990-12-20  |  102KB  |  2,129 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.                                       
  14.                                                                
  15.                                                                            
  16.                                                                            
  17.                                     ////////    //    //    //   
  18.                                    //    //    ///   //    //    
  19.                                   //    //    ////  //    //     
  20.                                  ////////    // // //    //      
  21.                                 //          //  ////    //       
  22.                                //          //   ///    //          
  23.                               //          //    //    ///////    
  24.                                                                            
  25.                                                                            
  26.                                                                        
  27.                                                                       
  28.                                                                       
  29.                                       Pascal NewsLetter         
  30.                                           Issue #5
  31.                                        December, 1990             
  32.                                                                       
  33.                                                                       
  34.                                       Editor: Pete Davis         
  35.                                                                       
  36.                                                                       
  37.                                                                       
  38.                                                                       
  39.                                                                       
  40.                                                                       
  41.                                                                       
  42.                                                                       
  43.                                                                       
  44.                                                                       
  45.                                                                       
  46.                                                                       
  47.                                                                           
  48.                         The Programmer's Forum BBS is the home of
  49.                         PNL. It can be reached in Washington, DC at
  50.                         (202)966-3647. Information is available 
  51.                         through the following locations:        
  52.                                            
  53.                         FidoNet:  Pete Davis@1:109/138           
  54.                         GEnie:    P.DAVIS5                          
  55.                         BitNet:   HJ647C@GWUVM & UE356C@GWUVM
  56.                         InterNet: HJ647C@GWUVM.GWU.EDU 
  57.                                or UE356C@GWUVM.GWU.EDU
  58.                         Uucp:     Pete.Davis@f138.n109.z1.fidonet.org
  59.  
  60.  
  61.                                                                         2
  62.  
  63.                                   Table of Contents
  64.  
  65.  
  66.  
  67.                Introduction ...............................  3  (P.D.)
  68.  
  69.  
  70.                The Lazy Programmer's Guide
  71.                to Graphics in Pascal ......................  4  (R.M.)
  72.  
  73.  
  74.                Introduction to Multiple Concept
  75.                Pascal Programming ......................... 15  (P.R.)
  76.  
  77.  
  78.                For Beginners .............................. 22  (B.G.)
  79.  
  80.  
  81.                Recursion is Easy .......................... 32  (C.B.)
  82.  
  83.  
  84.                Conclusion ................................. 38  (P.D.)
  85.  
  86.  
  87.                Distribution List .......................... 40
  88.  
  89.  
  90.  
  91.  
  92.  
  93.                
  94.  
  95.              P.D. -> Pete Davis          (Editor-in-Chief, Writer)
  96.              R.M. -> Richard A. Morris   (Editor-Over-the-Pond, Writer)
  97.              B.G. -> Bob Gowans          (Staff writer)
  98.              P.R. -> Paul Robinson       (Contributing writer)
  99.              C.B. -> Chris Burke         (Contributing writer)
  100.  
  101.                                                                         3
  102.  
  103.                                      Introduction
  104.  
  105.                   Well,  finally getting to  another issue of  the Pascal
  106.              NewsLetter. We're making  a few changes in  the organization
  107.              of  PNL. First of  all, I've  promoted myself  to Editor-in-
  108.              Chief. That's really what I've been all along, but it was to
  109.              make room for some new titles.
  110.  
  111.                   We've got a  new staffer, Richard  A. Morris, with  the
  112.              distinguished title of  'Editor-Over-the-Pond'. Richard will
  113.              be a collection point in Australia for PNL contributions and
  114.              will be editing  and sending them on to me  for inclusion in
  115.              the NewsLetter.  For a profile  of Richard, read the  end of
  116.              his  article.   If  you   live  in   Australia,  send   your
  117.              Contributions  to Richard A. Morris. His Fido-Net Address is
  118.              3:640/378. His system's phone number is 61-7-878-1194.
  119.  
  120.                   Richard is also writing "The Lazy Programmer's Guide to
  121.              Graphics in Pascal", a series of articles about, you guessed
  122.              it,  graphics programming  in Pascal.  It's   very  thorough
  123.              coverage of  graphics, so  many of you  will surely  find it
  124.              interesting.
  125.  
  126.                   Many  of  you probably  already  know that  I  had been
  127.              planning on  putting the  newsletter  out as  'Subscription-
  128.              only'.  Well, I  ran into  some problems  un-related to  the
  129.              newsletter which have forced me to  postpone, at least until
  130.              summer, this course.
  131.  
  132.                   Also,  I  would like  to  thank everyone  who  has been
  133.              contributing. It  seems that  the number  of submissions  is
  134.              increasing slightly, which is a  terrific bonus. If you  can
  135.              keep them coming in, the newsletter just might find a way to
  136.              come out a bit more often. 
  137.  
  138.                   In  this  issue, Paul  Robinson will  be talking  a bit
  139.              about  writing large programs in Pascal  and will cover some
  140.              programming  techniques. Bob  Gowans  continues his  popular
  141.              "For  Beginner's" column,  and last,  but  not least,  Chris
  142.              Burke shows you how simple recursion can be.
  143.  
  144.                   Well, that's about it for  this issue. I hope you enjoy
  145.              it.
  146.  
  147.                                                                         4
  148.  
  149.                    The Lazy Programmers Guide to Graphics in Pascal
  150.                                  by Richard A. Morris
  151.                                     Fido 3:640/378
  152.                                  Brisbane, AUSTRALIA
  153.  
  154.                   I have been  running a BBS and reading  FIDO echoes for
  155.              some years  now and  invariably the  first  2 things  Novice
  156.              programmers  want to  write with  their new  language are  a
  157.              better BBS, and a better Graphic Game.  Well I'll leave  the
  158.              intricate subject  of Data  communications to  the "Build  a
  159.              better Mousetrap "experts, and Game theory to the Academics,
  160.              Rather  in  the  next  6  Articles  I'll  discuss   Graphics
  161.              programming with Turbo Pascal.
  162.  
  163.                   The Idea behind the Lazy programmers Guide, is that  if
  164.              you are like  me, you often wondered how easy it would be to
  165.              do some particular programming task,  but never had the time
  166.              or inclination to  get around to opening the  manual at that
  167.              section.  Well this article is both for the  novice, and the
  168.              experienced  (Lazy Programmer) and  will take you  from very
  169.              simplistic exercises to quite complex Graphic programming in
  170.              a  short  time,  by  program  examples,  and  prodding  your
  171.              imagination to experiment a bit :-).
  172.  
  173.                   These articles are based on Turbo Pascal on the PC, and
  174.              I  apologize  in  advance  to   those  not  using  that,  in
  175.              particular  versions  4,  5, and  5.5  (And  I apologize  in
  176.              Advance to all Americans as I intend to use the word Color a
  177.              lot :-). I  am sure that the  topics I intend to  cover will
  178.              have some  relevance for  all Graphic  programming. I  don't
  179.              promise  that you  will be  able  to write  a better  Flight
  180.              Simulator (Although if you do  I want a mention :-)  but you
  181.              will understand a bit more about how it's done, and probably
  182.              gain a lot of respect for these Graphic Wizards.
  183.  
  184.                   The articles will  assume that you have  some knowledge
  185.              of  programming   concepts  (Such  as   Binary  mathematics,
  186.              Trigonometry)  and Turbo Pascal  (there will be  very little
  187.              handholding  :-), and will take  you from simple graphics to
  188.              quite Advanced programming concepts.
  189.  
  190.              The Articles will comprise the following Topics;
  191.                                                              
  192.                      Basic Graphics with Turbo Pascal GRAPH unit.
  193.                      Graphs, Statistics, and windows with the GRAPH unit.
  194.                      Simple Animation and Sprites using the GRAPH unit.
  195.                      User defined programming in the GRAPH Unit
  196.                      Writing Directly to the EGA/VGA.
  197.                      Animation using Direct writes to the EGA/VGA.
  198.                      Three Dimensional Graphics directly to the EGA/VGA.
  199.  
  200.  
  201.  
  202.                                                                         5
  203.  
  204.  
  205.              ------------------------------------------------------------
  206.              The Lazy Programmers guide to Turbo Pascal Graphics - Part 1
  207.                      - Basic Graphics with the GRAPH unit -
  208.              ------------------------------------------------------------
  209.  
  210.  
  211.              A Brief  History of  PC Displays -  Apologies to  S. Hawkins
  212.              :-).
  213.              ------------------------------------------------------------
  214.  
  215.                   Graphics  in  the  Personal  computer  world  refer  to
  216.              non-text  display information.  The original  PC  released a
  217.              decade  ago,  was   equipped  with  a  display   called  the
  218.              Monochrome Display, and a  driver called (Surprise surprise)
  219.              the   Monochrome  Display  Adapter.    This  Display  had  a
  220.              resolution   of  720x350  and  displayed  ONLY  the  IBM  PC
  221.              character set in black and white.
  222.  
  223.                   It was not long before the popularity of computers such
  224.              as the Apple II, with it's bit mapped display, caused demand
  225.              for a  graphic display, and  the Hercules (from a  PC add-on
  226.              company  Hercules  Computer  Technology)  was  born.     The
  227.              Hercules  still displayed  data in black  and white,  but it
  228.              allowed you  to show bitmapped  graphics.  Soon IBM  got the
  229.              hint and released  the Color Graphics Adapter  with 16 color
  230.              text and 4 color bit mapped  graphics, unfortunately the CGA
  231.              design  featured a  lot  of compromises  such as  display to
  232.              inferior  composite  displays,   and  offered  poor  display
  233.              resolution (320x200), but  it did have Color, and  it is one
  234.              of the most popular displays around.
  235.  
  236.                      Eventually due  to increasing  market pressure  from
  237.              companies  like Apple, Atari, and Commodore, IBM brought out
  238.              a reasonable display  called the ECD, and drove  it with the
  239.              Enhanced  Color Adapter, this  gave programmers access  to a
  240.              resolution of  640x350 with  16 simultaneous  Colors from  a
  241.              palette of 64.  Lately VGA technology has become  a standard
  242.              and it increases  displays up to 640x480 and  256 colors (at
  243.              320x200).   These articles will  concentrate on the  EGA and
  244.              VGA modes, but the GRAPH  unit stuff will cover some aspects
  245.              of general graphic  device programming, and this  first part
  246.              only requires a CGA Screen..
  247.  
  248.  
  249.              BGI - The Borland Graphics Interface
  250.              ------------------------------------
  251.  
  252.                   Due to the nature of  the PC market, any programmer who
  253.              wrote his code  for any particular Graphic  standard limited
  254.              his earnings by limiting his User base to only that machine.
  255.              True, most of  the standards are Downward  compatible, which
  256.  
  257.  
  258.                                                                         6
  259.  
  260.              means that  a CGA only application  would run on a  VGA, but
  261.              given the choice  a VGA owner would surely  choose a product
  262.              that displayed VGA graphics. 
  263.  
  264.                   Until  Borland brought out BGI's most Languages did not
  265.              support Graphics at  all, relying on third  party toolboxes,
  266.              with Turbo Pascal and Turbo C Borland introduced the concept
  267.              of a  Graphic Interface whereby  a programmer wrote  code to
  268.              call the  BGI  which would  then  do all  the  hard work  of
  269.              working out what device it was talking to and how to display
  270.              that information.
  271.  
  272.                   This is a great concept,  as it provides portability of
  273.              programs  across  graphic  devices,  but of  late  a  lot of
  274.              programmers  have decided  to bypass  Borlands interface  to
  275.              talk  instead directly  with the  graphic  device. The  main
  276.              reason for this  is speed, Borland Drivers  use the computer
  277.              BIOS in  a lot of  cases (Which itself wastes  time deciding
  278.              what  device it  is  talking to),  and are  themselves quite
  279.              slow,  hence I  shall devote  a  fair bit  of time  in later
  280.              Articles on programming Directly to the Graphic device.
  281.  
  282.  
  283.              Setting up to display Graphics
  284.              ------------------------------
  285.  
  286.              Firstly to  Show graphics  on our monitor  we must  tell the
  287.              device to get  into graphics mode, at the  end of displaying
  288.              what we want we must also return  the system to the original
  289.              display mode.  Additionally as  we will be using BGIs during
  290.              this article,  we must tell  Turbo pascal where to  find our
  291.              BGI control files.
  292.  
  293.                   A sample of a simple  program to get into graphics mode
  294.              display a line of text  (More of this in this article),  and
  295.              go back to text mode is in the following program put it into
  296.              a  file called GRAPH_TE.PAS.  To compile it load it into the
  297.              editor, change  line 7  to make BGI_Directory  point to  the
  298.              directory  you have  put all  the BGI  files into  (eg:I use
  299.              c:\TP\BGI).
  300.  
  301.              ~ Prog 1 ~~~~~~GRAPH_TE.PAS~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  302.              {$M 16384,16384,655360}
  303.              Program Graph_Test;
  304.              Uses
  305.                CRT,
  306.                GRAPH;
  307.              Const
  308.                BGI_Directory = 'C:\TP\BGI';
  309.              var
  310.                GraphDriver   : Integer;
  311.                GraphMode     : Integer;
  312.  
  313.                                                                         7
  314.  
  315.                ErrorCode     : Integer;
  316.                tempstr       : String;
  317.              begin
  318.                GraphDriver := Detect;
  319.                InitGraph(GraphDriver,GraphMode,BGI_Directory);
  320.                ErrorCode := GraphResult;
  321.                if ErrorCode <> grok then
  322.                begin
  323.                      Writeln('Error initialising Graphics :',ErrorCode);
  324.                      Writeln('Error Message :',GraphErrorMsg(ErrorCode));
  325.                      Halt(1);
  326.                end;
  327.  
  328.                {Graphics stuff begins}
  329.                Str(GraphMode,TempStr);
  330.                OutText('We are in Graphics mode number :'+TempStr);
  331.                Str(GraphDriver,TempStr);
  332.                OutText('This is Device number :'+TempStr);
  333.                {End of Graphics stuff}
  334.  
  335.                delay(1000);
  336.                CloseGraph;
  337.              end.
  338.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  339.  
  340.                   O.K. let's dissect this test program, firstly in line 4
  341.              we USE the  GRAPH unit, this will  give us access to  all of
  342.              the  graphics  routines,  and  constants.  We   declare  the
  343.              directory  that all  the  BGI  files will  be  found into  a
  344.              constant, and declare  4 variables GraphDriver to  store the
  345.              type  of graphics  device we  have, GraphMode  to store  the
  346.              graphics mode  we  will use,  ErrorCode to  store any  error
  347.              numbers,  and  TempStr  to  temporarily  store  integers  as
  348.              strings.
  349.  
  350.                   Then we set  GraphDriver to the GRAPH  constant DETECT.
  351.              DETECT  is  defined as  0  and  will  tell Turbo  Pascal  to
  352.              automatically detect the Graphic device connected to the PC,
  353.              and  select for us the  maximum available Graphics mode. The
  354.              next line calls  the GRAPH function INITGRAPH,  we tell this
  355.              function  what device  to talk  to  (or AUTO  detect in  our
  356.              case), which mode we want (In this case the Auto detect will
  357.              select one for us), and the  location of the BGI files.   We
  358.              can actually pre-select the type of device by specifying the
  359.              GraphDriver and  GraphMode before  running InitGraph,  as in
  360.              the following inset (Replace Grafdriver := detect).
  361.  
  362.              ~~~~~~~~~~~~~~~~~~~~~~
  363.                GraphDriver := CGA;
  364.                GraphMode := cgac0;
  365.              ~~~~~~~~~~~~~~~~~~~~~~
  366.  
  367.  
  368.                                                                         8
  369.  
  370.                   This will set up the  Graphic device for working with a
  371.              CGA compatible device,  running in mode CGAc0, or  the first
  372.              CGA color mode.  InitGraph allocates some memory on the heap
  373.              to work  with, so you  must have some heap  memory available
  374.              (Hence the  $M directive  in line 1),  such as a  general 4K
  375.              buffer for graphics, and space to put the BGI file.
  376.  
  377.                   The GRAPH  function GraphResult will have  an errorcode
  378.              after most  GRAPH routines and  will be zero if  the routine
  379.              proceeded without error, or will contain an error  number if
  380.              an error occurred, the function GraphErrorMsg can give you a
  381.              textual error message if you send  it the error number as we
  382.              have  in the test  program.  If an  error occurs the program
  383.              describes the error and aborts.
  384.  
  385.                   Assuming  successful  initialization   of  the  Graphic
  386.              system the  next step is  to perform the  Graphics routines,
  387.              which in this case is to write  out a message describing the
  388.              Device  that autodetect found and the  Mode.  We have to use
  389.              the str  routine to  convert integers into  strings, as  the
  390.              Graph  text writing  expects a  string as  a  parameter, and
  391.              can't use  the abilities of  write and writeln.   Finally we
  392.              close  the graphics  drivers  with CLOSEGRAPH.  Close  Graph
  393.              releases all memory  assigned by InitGraph and  restores the
  394.              original text mode.
  395.  
  396.                   Now when you  run the program  it will quickly  display
  397.              the  graphics data,  and jump  back  to text  mode, so  I've
  398.              inserted a delay in before the call to close graph.  You may
  399.              notice  a delay  before loading  graphics  while the  system
  400.              loads the BGI file, in some systems this may be unacceptable
  401.              or  you may  wish to  distribute just  on  EXE file  and not
  402.              include a whole  lot of  BGIs, so Borland  have given you  a
  403.              demo of how to do this in the example file BGILINK.PAS.
  404.  
  405.                   If you have problems  with this sample file  you should
  406.              check that you have a  graphics capable device, and that the
  407.              BGI files are indeed where you specified them.
  408.  
  409.  
  410.              Displaying Pixels
  411.              -----------------
  412.  
  413.                   O.K. so far you've managed to Display some funny shaped
  414.              text on the screen, Big Deal you say.  Well from here on  in
  415.              this part we will use the program Graph_Test,  to set up the
  416.              graphics device, and close it after use, and in place of the
  417.              above Graphics stuff  (In this case the OUTTEXTs)  we put in
  418.              specialized code.   The next step is  to display a  point on
  419.              the screen, we call one of these a PiXel or Picture Element.
  420.  
  421.                   As  you   know  different  Display   technologies  have
  422.  
  423.  
  424.                                                                         9
  425.  
  426.              different  Screen resolutions  (Pixels  on  the Screen)  for
  427.              example you fit 320 pixels  across and 200 down in CGA  mode
  428.              5.   In the BGI routines, you can  put a pixel in a location
  429.              that is not  on the screen.  This may seem strange, but when
  430.              you realize  that under EGA you can put  a pixel in the last
  431.              column at column 639 (the first  column is always 0 so 0-639
  432.              = 640 pixels), which would be way of the screen in CGA.  For
  433.              the purposes  of this Article  we'll do most of  our work in
  434.              the range of 0 - 99 columns  and 1 - 99 rows, which will  be
  435.              displayable on all monitors.
  436.  
  437.                   The  routine  to display  a  pixel  on  the  screen  is
  438.              (Surprise) PutPixel(x,y : Integer; Color:  word) X and Y are
  439.              not  surprisingly Column and  Row coordinates, and  Color is
  440.              the  color of  the pixel.   O.K. so  lets do  some Graphics.
  441.              Insert  the  following  declarations  at  the  beginning  of
  442.              Graph_Test, and the routine in the Graphics stuff section.
  443.  
  444.              ~ Declarations ~~~~~~~~~~~~~~~~~~~~~~~~
  445.              VAR
  446.                Counter : Integer;
  447.                Color : Word;
  448.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  449.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  450.                Color := 1;
  451.                For Counter := 0 to 99 do
  452.                begin
  453.                  PutPixel(0      ,Counter,color);
  454.                  PutPixel(99     ,Counter,color);
  455.                  PutPixel(Counter,0      ,color);
  456.                  PutPixel(Counter,99     ,color);
  457.                end;
  458.                PutPixel(50 ,50 ,Color);
  459.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  460.  
  461.                   This routine will Firstly  set the variable color  to 1
  462.              (The  first available color, in which  case all devices will
  463.              show a color  distinct from the background color),  which in
  464.              most modes is Dark blue, in  the 320x200 cga modes this will
  465.              be  Green, or Cyan.  The system then counts from 0 to 99 and
  466.              puts a  box on the screen, by plotting  a point in the left,
  467.              right, top and Bottom edge.  To see how it does  this dot by
  468.              dot put  the line DELAY(100) before the end in the FOR loop,
  469.              you will see each dot  being drawn.  Then it will  put a dot
  470.              almost in the middle of the box, depending on the resolution
  471.              of  your display  mode, the  box  could be  anything from  a
  472.              perfect  square to  an  elongated  rectangle,  GRAPH  has  a
  473.              procedure  called  GetAspectRatio  which will  tell  you the
  474.              ratio you may use to draw a perfect square (We'll talk about
  475.              this later on), and various functions and  procedures to ask
  476.              the Graphics device how wide and tall  (in pixels) it is, we
  477.              will discuss these in the next article on Graphs.
  478.  
  479.  
  480.                                                                        10
  481.  
  482.                      Play  with   the  colors  for  your   default  (Auto
  483.              detected) mode,  then try playing  with the  Graphdevice and
  484.              Graph mode, to get the hang of your Graphics device, as  you
  485.              will  need  to know  later  on  about  the  capabilities  of
  486.              your system.  You can also  move the  x,y  position  of  the
  487.              single  pixel, or even draw some simple shapes.
  488.  
  489.                   An example of  a little function to draw  a shape would
  490.              be to stick this line in the FOR loop.
  491.  
  492.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  493.                                                                          
  494.              PutPixel(Counter,50+trunc(sin((counter/100)*2*pi)*20),color)
  495.              ;
  496.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  497.  
  498.                   It plots a point for  each x position of counter, based
  499.              on a sin function (A Turbo function  that gives a value on a
  500.              sin curve  (Wave !?!)  between -1 and  1 for  every position
  501.              between 0 and  2*Pi radians).  TRUNC converts  the Sin value
  502.              from  a  Real  into  an  integer  for  PutPixels  Y   value,
  503.              sin((Counter/100)*2*pi) gives  a real  between -1  and 1  as
  504.              (Counter/100) goes from 0 to  almost 1, and we multiply this
  505.              by 20 to  make the wave oscillate between 50-20 and 50+20 to
  506.              put the wave in the middle of the box.
  507.  
  508.  
  509.              Lines, Arcs and other Objects
  510.              -----------------------------
  511.  
  512.                   Drawing a  line is  a bit  slow plotting  a pixel  at a
  513.              time,  so Turbos  GRAPH  unit includes  a  LINE function  so
  514.              firstly  we'll replace  our FOR  Loop  box Drawing  routines
  515.              with;
  516.  
  517.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  518.                SetLineStyle(SolidLn,0,NormWidth);
  519.                SetColor(1);
  520.                Line(0,0,0,99);
  521.                Line(0,99,99,99);
  522.                Line(99,99,99,0);
  523.                Line(99,0,0,0);
  524.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  525.                   You  will also notice that LINE doesn't include a color
  526.              parameter, GRAPH has a routine called SETCOLOR (Which we set
  527.              before we draw the lines) which  defines a color to be  used
  528.              by all line and object  drawing routines.  Graph has another
  529.              surprise  with a routine called SETLINESTYLE which allows us
  530.              to  select the  style, pattern,  and thickness of  the lines
  531.  
  532.  
  533.                                                                        11
  534.  
  535.              we'll  draw,  again  I've  included  that  one  above for  a
  536.              SolidLn, but  you  might like  to  try styles  of  DottedLn,
  537.              CentreLn,  or  DashedLn  and   a  Thickness  of  Thickwidth.
  538.              Pattern is a special value we'll discuss in the next topic.
  539.  
  540.                      There is  an even  Better  method to  display a  Box
  541.              called RECTANGLE, which  combined the 4 lines  commands, try
  542.              this.
  543.  
  544.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  545.                SetLineStyle(SolidLn,0,NormWidth);
  546.                SetColor(1);
  547.                Rectangle(0,0,99,99);
  548.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  549.                      Now try  this, it uses three more  line based object
  550.              drawing routines;
  551.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  552.                SetLineStyle(SolidLn,0,NormWidth);
  553.                SetColor(1);
  554.                Rectangle(0,0,99,99);
  555.                Circle(50,50,40);
  556.                Arc(50,60,225,315,20);
  557.                Ellipse(40,40,0,360,5,10);
  558.                Ellipse(60,40,0,360,5,10);
  559.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  560.                   What these routines do is Draw a Circle with the centre
  561.              at  50,50 with  a radius  of  40 pixels  (This routine  uses
  562.              GetAspectRatio to makes as round a circle as  possible), Arc
  563.              draws a  part of a circle with a  centre at 50,60 (10 pixels
  564.              below  the  centre of  the  circle) going  from  225 degrees
  565.              (Unlike the  Trigonometric functions  the Graphics  routines
  566.              represent angles in Degrees, starting from 0 horizontally to
  567.              the right) to 315  degrees with a radius  of 20 pixels,  the
  568.              two  Ellipses  draw  two  identical  squashed  circles  with
  569.              centres 10  pixels either side  of the middle point,  and 10
  570.              pixels above  it, each  ellipse goes from  angle 0  around a
  571.              full circle to 360, and with a x radius of  5 and a Y radius
  572.              of 10.  If this explanation seems a bit obtuse, run the demo
  573.              first and you'll see what I mean <grin>.
  574.  
  575.                   The  Last  Line  Based Object  drawing  routine  is the
  576.              PolyDraw  routine which will  draw any polygon,  although it
  577.              needs a bit of setting up.   What you have to do is define a
  578.              variable as  an array of  pointType which is a  GRAPH global
  579.              type,  a record  of (x,y)  coordinates.   Then you  fill the
  580.              array  elements with x,y coordinate data  (I often use Graph
  581.              paper to  work out how I'm going to  do a shape), and simply
  582.              call the DrawPoly routine with the number of points, and the
  583.              Shapearray, try  this one which  draws two triangles  on our
  584.              face shape;
  585.  
  586.              ~ Delcaration ~~~~~~~~~~~~~~~~~~~~~~~~~
  587.  
  588.  
  589.                                                                        12
  590.  
  591.                Triangle : Array[1..4] of PointType;
  592.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  593.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  594.                Triangle[1].x := 50;
  595.                Triangle[1].y := 85;
  596.                Triangle[2].x := 20;
  597.                Triangle[2].y := 75;
  598.                Triangle[3].x := 20;
  599.                Triangle[3].y := 95;
  600.                Triangle[4].x := 50;
  601.                Triangle[4].y := 85;
  602.                DrawPoly(4, Triangle);
  603.                Triangle[2].x := 80;
  604.                Triangle[3].x := 80;
  605.                DrawPoly(4, Triangle);
  606.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  607.              Patterns and fills
  608.              ------------------
  609.  
  610.                   O.K. from the previous program, add the following lines
  611.              after that last DrawPoly routine;
  612.  
  613.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  614.                SetFillStyle(solidFill,Color);
  615.                FloodFill(50,5,Color);
  616.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  617.                   A fill is a  bit like a color-in that kids  do, it will
  618.              fill an  area with  a color.   Now this one  takes a  bit of
  619.              explaining, firstly SetFillStyle  sets the type of  fill any
  620.              solid routine will use, and the color that it  will color in
  621.              with, in this case it will be a SolidFill, you can fill with
  622.              diagonal  lines  (SlashFill),  or hatchs  (HatchFill),  dots
  623.              (CloseDotFill) or  others, play around with it.   The second
  624.              line calls the  fill, by specifying the x and  y position of
  625.              any point within the area  to fill, and the color that  will
  626.              border the area.
  627.  
  628.                   If there  are any breaks  in the border then  the flood
  629.              fill  will leak through, try  putting this routine to remove
  630.              one of  the bowties edges  in before the  FloodFill Routine,
  631.              you'll  notice  the  floodfill will  bleed  into  the second
  632.              triangle;
  633.  
  634.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  635.                SetColor(0);
  636.  
  637.              Line(Triangle[2].x,Triangle[2].y,Triangle[3].x,Triangle[3].y
  638.              );
  639.                SetColor(1);
  640.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  641.  
  642.                   You can  draw the  polygon and fill  at the  same time,
  643.  
  644.                                                                        13
  645.  
  646.              with  a GRAPH routine  called FillPoly, remove  the previous
  647.              routine to  delete  the  edge  of  the  bowtie,  remove  the
  648.              floodfill, and Change  the two DRAWPOLYs into  FILLPOLLY and
  649.              put 
  650.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  651.                SetFillStyle(WideDotFill,Color);
  652.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  653.              anywhere before both FillPolys and the routines will perform
  654.              a poly  draw AND  a fill  at the  same  time.   You can  use
  655.              FillEllipse in  the same way to draw and fill an ellipse, or
  656.              Bar to draw and fill a rectangle.
  657.  
  658.  
  659.              Text and Fonts
  660.              --------------
  661.  
  662.                   To  draw  text  there are  several  commands  the first
  663.              SetTextStyle loads up BGI files for the Font type (Much like
  664.              initgraph sets up the Device BGI files), sets  the direction
  665.              of the text (Try this next procedure with VertDir instead of
  666.              HorizDir, and set the text  to start at 10,5), and  the size
  667.              of  the  characters.  The  second  Command  OutTextXY(X,Y  :
  668.              Integer;Text  : String) sends  text of the  defined Style to
  669.              the output port at the requested X,Y location.
  670.  
  671.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  672.                SetTextStyle(DefaultFont,HorizDir,1);
  673.                OutTextXY(20,5,'Mr Happy');
  674.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  675.  
  676.                   Try  different   commands  such   as  different   fonts
  677.              (TriplexFont, GothicFont), different  sizes (Each fonts text
  678.              will be a different size), and different orientations.
  679.  
  680.                   One  major  problem  with  Ad  hoc  text  placement  in
  681.              Graphics modes is working out where to put the next line, as
  682.              you probably won't know where the current text  finishes and
  683.              the  next should  begin.    Turbo  provides  two  procedures
  684.              TextHeight and TextWidth for just this problem.  Simply said
  685.              they return the size in pixels  take up by a string.   Let's
  686.              go straight to an example, and I'll show you what I mean.
  687.  
  688.              Remove  all  the  old graphic  stuff  leaving  only  the Box
  689.              routine, and after drawing the box, add the following;
  690.  
  691.              ~ Routine ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  692.                SetTextStyle(DefaultFont,HorizDir,1);
  693.                Charheight := TestHeight('M');
  694.                OutTextXY(20,5,'Simple example');
  695.                OutTextXY(20,5+textheight,'of text spaced');
  696.                OutTextXY(20,5+textheight+textheight,'at even heights');
  697.              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  698.  
  699.  
  700.                                                                        14
  701.  
  702.                   As you  see you will  get each new line  starting after
  703.              the  previous   line  has  finished,   regardless  of  font,
  704.              character, or graphics device.
  705.  
  706.  
  707.              Summary
  708.              -------
  709.  
  710.                   Well I hope  I haven't offended too  many sensibilities
  711.              with the  simplistic nature of  the exercises, we  have gone
  712.              over  some  very  basic  Graphic  concepts  here,  that  are
  713.              fundamental to  further understanding  graphic manipulation.
  714.              Next  PNL  I  will be  discussing  Business,  mathematic and
  715.              Scientific Graphics such as Bar, Pie, Scatter, Hi_Lo graphs,
  716.              the graphing of mathematic functions in 2 and 3  dimensions,
  717.              and Fractal representations such as Sierpenski,  Mandlebrot,
  718.              and  Benoit sets.   As  well as  topics, like  windows, Auto
  719.              Scaling graph  axes, and  further discussion  of aspects  of
  720.              text drawing.
  721.  
  722.              Author
  723.              ------
  724.  
  725.                   Richard  Morris   is  the   Owner/operator  of   KHIRON
  726.              Software,  in Brisbane AUSTRALIA, a company that specializes
  727.              in  Graphic  Databases  in  Turbo  Pascal  for  Health  care
  728.              professionals,  as well as  providing contract staff  for as
  729.              diverse projects  as  Robotic process  control software,  to
  730.              various   Industry  support   software.  Current   Supported
  731.              Packages  DENTAPAC tm  -  Dental practice  management tools,
  732.              PHYSIOPAC tm - Phyiotherapy management tools, and ORTHOPAC -
  733.              Orthodontic practice management tools.
  734.  
  735.              References
  736.              -----------
  737.  
  738.              The Turbo Pascal Reference Guide
  739.              (C)89 Borland Int.
  740.  
  741.              Advanced Programmer's Guide to the EGA/VGA
  742.              George Sutty/Steve Blair
  743.  
  744.              Advanced MsDos
  745.              Ray Duncan
  746.  
  747.              INTER490
  748.              Ralf Brown
  749.  
  750.  
  751.                                                                        15
  752.  
  753.                 (C) Copyright 1990, Tansin A. Darcos & Co.  Commercial
  754.                           Reproduction rights are reserved.
  755.  
  756.                    Introduction to Multiple-Concept Pascal Programs
  757.                                     Paul Robinson
  758.  
  759.                   Most large or commercial programs  tend to do  a number
  760.              of things.   I was trying to  do a  program that would count
  761.              all the words  in a text  file - which  might be almost  any
  762.              line format,  and produce   an alphabetical  list  of words.
  763.              This meant that I had to do several things:
  764.  
  765.                   o  Read a  file that  might have Carriage Return 
  766.                     ("CR")  followed by Line  Feed ("LF")  for an
  767.                     end  of line,  LF then  CR, LF  only,   or CR
  768.                     only, or  might be  from one  of those  weird
  769.                     programs that  just generates  "stream ASCII"
  770.                     in which it takes words  until the  line is  
  771.                     full then  at the next space issues a "soft" 
  772.                     carriage  return.   The only  requirement was
  773.                     that  the  file  be   non-coded,  i.e.   that
  774.                     characters  appear as normal character values
  775.                     (Wordstar, for example,  puts a high-bit code
  776.                     on some  words to  use as  paragraph or  line
  777.                     breaks).
  778.  
  779.                   o  When reading the words, store them in memory.  The
  780.                     program might read a small  file or  it might
  781.                     read a 1/2  million word book, so  the number
  782.                     of  words would  be  indeterminant, and   the
  783.                     word  sizes  would  all be different.
  784.  
  785.                   o  List each word and the number of times used, in
  786.                     alphabetical order.  The first  qualification
  787.                     precluded  the   use  of   Pascal's  standard
  788.                     READLN/EOLN  construct  to check  for  end of
  789.                     line.   This meant I'd have  to read the file
  790.                     in  on a character  by character basis.   The
  791.                     second provision  was because,  with as  much
  792.                     memory as is on a PC, there is really no need
  793.                     - unless  you get  a huge file - to  use disk
  794.                     space  to store word  counts (also because of
  795.                     something I was trying to do that I wanted to
  796.                     use    a  in-memory  word  list).  The  third
  797.                     provision  was    what I    had  wanted:   an
  798.                     alphabetical word list.  (If I had  been more
  799.                     concerned with the  number of  uses, I  would
  800.                     have had the  words listed in order by number
  801.                     of usages rather  than alphabetically). These
  802.                     provisions  made  the   choice  of    using a
  803.                     linked list quite obvious. The questions that
  804.                     came  up included what type of linked list to
  805.  
  806.  
  807.                                                                16
  808.  
  809.                     use and  how to implement  it.  That  will be
  810.                     discussed below.
  811.  
  812.  
  813.  
  814.                            Understanding Pointer Variables
  815.                                     Paul Robinson
  816.  
  817.                   One of  the things  I needed to do one day was read one
  818.              or more  disk files and  create an alphabetized list  of the
  819.              words in  each file,  for something I  was working  on.    I
  820.              wanted to   store  the list  of words  used in  the file  in
  821.              memory because I did not want to spend a lot of time reading
  822.              and  writing   the disk in  addition to  all the  disk reads
  823.              being used to  read the original file(s).   Since the number
  824.              of words   to  be   stored  would   vary, storing   them  in
  825.              arrays might either not provide enough memory space or waste
  826.              a lot of memory.
  827.  
  828.                   Pascal (and   other languages)   have a   capability in
  829.              which a  variable can point  to  a  block  of storage   that
  830.              only   exists after   the program explicitly requests  to be
  831.              issued that storage.  Arrays and variables  are created (for
  832.              the main program) when it is executed,  and exist  until the
  833.              program  ends.     This  special   storage    is   allocated
  834.              dynamically   if,  as   and when  needed, by the  programmer
  835.              specifically asking  to  be   given   a   block   of    this
  836.              memory.    The programmer  can   also give back  this memory
  837.              when finished using it, and perhaps even re-use it later on.
  838.  
  839.                   To access this dynamic memory, the programmer creates a
  840.              class   of variable  called a   pointer.    A pointer   is a
  841.              variable that describes  a memory location indirectly.   Let
  842.              me explain that a little closer.
  843.  
  844.                   An ordinary variable  exists at a specific  location in
  845.              memory, and  contains a  value  such  as   a number,   or  a
  846.              character (or  two). This is an ordinary, direct access to a
  847.              value.  A pointer, however, goes  one step  further, in that
  848.              it contains not a value, but the address of a value.
  849.  
  850.                   For example, let me examine a record:
  851.  
  852.                   TYPE
  853.                      maxstring = STRING[255];
  854.  
  855.                      tokp = ^tok ;
  856.                      tok  = RECORD
  857.                                 next  : tokp ;
  858.                                 count : LONGINT ;
  859.                                 token : maxstring;
  860.                             END ;
  861.                                                                        17
  862.  
  863.                   The  first    item  indicates    that  the   identifier
  864.              'maxstring'  is a  string  of  the maximum  size.   Next,  I
  865.              indicate that the  identifier 'tokp' is a pointer to (that's
  866.              what  the  ^ indicates: "Pointer to")  the identifier 'tok'.
  867.              But tok is  not defined until after  tokp.  This is  the one
  868.              exception to  the rule  in Pascal that  everything   must be
  869.              defined  before use; pointers may refer to identifiers which
  870.              are not defined when the pointer is.
  871.  
  872.                   Tok is  a record beginning  with a 'next'  field, which
  873.              since we know tokp is a pointer,  that 'next'  is  a pointer
  874.              to another record of the same type.  The 'count' variable is
  875.              a long integer,  and 'token' is a string  of maximum length.
  876.              Why is   there yet   another pointer   when one   is already
  877.              defined?   The 'next' field  is what is called  a 'traverse'
  878.              pointer.  In order to  find records  in  a linked list,  you
  879.              have  to be able to follow ('traverse') the list in whatever
  880.              order it is maintained.  The  way to  do this  is to  change
  881.              the   pointer that  looks at   a  record   from the  current
  882.              record to the  next one in the list.   This would   be  done
  883.              by   assigning  the  'next'  value   to  the  pointer  which
  884.              is referencing this   record.   Some  pointer  records  will
  885.              also carry a 'back' or 'prev'  pointer to go backward in the
  886.              list.   Note   that all  this has  done is  create a  set of
  887.              names so  that we can use this record - or the tokp pointer-
  888.              in  the program, but we  cannot yet use  them because we did
  889.              not define variables that do, like this:
  890.  
  891.                   VAR
  892.                        name:maxstring;
  893.                        T,t1: tokp;
  894.  
  895.                   We  still   can't  access   the   memory,  because  the
  896.              pointers do not really contain the  data, they  contain only
  897.              the address  of the  data.    We have to allocate the  space
  898.              for  that data   in order to be able to  access them.  There
  899.              are  two ways  that a programmer  can be   given access   to
  900.              dynamic   memory.    Both  require the    programmer pass  a
  901.              pointer  to  a  procedure  that  allocates  memory  to  that
  902.              pointer.
  903.  
  904.                   The first method is the NEW procedure, which is  called
  905.              in the form
  906.  
  907.                        NEW(T);
  908.  
  909.              however, in  our instance,  allocating 255 bytes  for   each
  910.              word  probably  wastes memory, especially  since  each  word
  911.              probably is no larger than 20 characters. There are two ways
  912.              around this:  pick  a  maximum and  assume no   word will be
  913.              larger  than that,  or size  the  records to  fit, which  is
  914.              option 2.
  915.  
  916.                                                                        18
  917.  
  918.                   The second  method involves   knowing what  the program
  919.              does; since I will know  that 'name' will contain the string
  920.              to be stored in the  'token' field of the tok  record.   So,
  921.              I could  allocate a  specific sized block  of memory  with a
  922.              special procedure available  in Turbo Pascal called  GETMEM,
  923.              and it  works like this:
  924.  
  925.                        GETMEM(T,LENGTH(NAME)+10);
  926.  
  927.              where  the first  argument is  the pointer  to use,  and the
  928.              second argument is the amount of memory in bytes to allocate
  929.              to the pointer.  The  LENGTH(NAME) value gives us the actual
  930.              size of the string, the  +10 is because the pointer takes  4
  931.              bytes, the longint  takes 4 bytes, the length  of the string
  932.              adds  one byte, and I want  the next allocation to come on a
  933.              word boundary.
  934.  
  935.                   In either the  NEW or GETMEM  options, the variable  is
  936.              now  ready for  use. We  can  access it  by referencing  the
  937.              pointer followed by a fieldname:
  938.  
  939.                        T^.Count := 1;      or   T^.Token := Name;
  940.                        T^.Token := Name;        T^.Count := 1;
  941.  
  942.                   Also, it is  usually best to   ensure that   any unused
  943.              or traverse pointers are cleared, so we should also say:
  944.  
  945.                        T^.Next := NIL;
  946.  
  947.              (NIL is a special value which indicates a pointer  is not in
  948.              use).
  949.  
  950.                   If we  later  add  another record, we have  to keep the
  951.              old one, so we might do something like this:
  952.  
  953.                        T1 := T;
  954.                        WHILE T1^.Next <> NIL DO
  955.                             T1 := T1^.NEXT;
  956.                        GETMEM(T1^.Next,LENGTH(Name)+10);
  957.                        T1 := T1^.Next;
  958.  
  959.                   (I am trying to simplify this  example.    Things  like
  960.              alphabetizing the  entries, checking  for duplicates,  etc.,
  961.              has been omitted.)
  962.  
  963.                   When finished with the memory pointed to by  a pointer,
  964.              you release it back to the system.  On some systems they use
  965.              MARK and  RELEASE, in which  you create a mark  pointer, and
  966.              store the current memory list in the marked pointer with
  967.  
  968.                        MARK(markpointer);
  969.  
  970.  
  971.                                                                        19
  972.  
  973.              then when you don't need the memory any more, you get rid of
  974.              it with
  975.  
  976.                        RELEASE(markpointer);
  977.  
  978.                   This cancels   all usage  of  the  NEW procedure   done
  979.              after the MARK procedure call.  Any pointers allocated after
  980.              that MARK are now  invalid.    Some systems do a  better job
  981.              at allocating memory, in which you use the NEW procedure (or
  982.              on Turbo Pascal, you  can   also  use  GETMEM),   then  when
  983.              you   don't  need a particular piece  of memory, you can use
  984.              DISPOSE (if  you  called  NEW) or  FREEMEM  (if  you  called
  985.              GETMEM).  You would use them like this:
  986.  
  987.                        NEW(T1);
  988.  
  989.                        ...
  990.  
  991.                        DISPOSE(T1);  
  992.  
  993.  
  994.                          (* OR *)
  995.  
  996.                        GETMEM(T1,LENGTH(NAME)+10);
  997.  
  998.                        ...
  999.  
  1000.                        FREEMEM(T1,LENGTH(NAME)+10);
  1001.  
  1002.                   Note: if  a program is  exiting, it does  not have   to
  1003.              release  the memory it allocated; the system will do so  for
  1004.              it.
  1005.  
  1006.                   Pointers do   not have  to  point to records.   In some
  1007.              systems,  pointers  are used  as  a  means to  simulate  the
  1008.              PEEK/POKE  function   from   BASIC,   as   in the  following
  1009.              example:
  1010.  
  1011.                   PP = ^CHAR;
  1012.                   VAR 
  1013.                        P: PP;
  1014.                        I: array[1..2] of integer absolute P;
  1015.                        Colr,Mono,Both:boolean;
  1016.  
  1017.                   BEGIN
  1018.                        I[2] := $B800;
  1019.                        I[1] := 0;
  1020.                        Colr := FALSE;
  1021.                        Mono := FALSE;
  1022.                        P^ := 'A';
  1023.                        IF P^ = 'A' THEN Colr := TRUE;
  1024.                        I[2] := $B000;
  1025.  
  1026.  
  1027.                                                                        20
  1028.  
  1029.                        I[1] := 0;
  1030.                        P^ := 'A';
  1031.                        IF P^ = 'A' THEN Mono := TRUE;
  1032.                        IF Colr and Mono THEN Both := True;
  1033.                        ...
  1034.  
  1035.  
  1036.                   This little  program segment checks  to see if  a color
  1037.              adapter is installed, then it  checks to see if a monochrome
  1038.              adapter  is  installed, by   checking the physical addresses
  1039.              to see   if there is memory in their  spaces.  This piece of
  1040.              code  is  here to  show that  a   pointer   can   point   to
  1041.              something   other   than a record.    Turbo Pascal   has the
  1042.              MemW[] and Mem[] arrays, but some compilers do not, and this
  1043.              is one way it may be simulated.
  1044.  
  1045.                              Understanding A Linked List
  1046.                                     Paul Robinson
  1047.  
  1048.  
  1049.                   Going back  to my original idea,   I wanted   to create
  1050.              an  alphabetized word  list.    I  wanted  merely  to   do a
  1051.              single linked list where each item points to the next one in
  1052.              memory.   If I  checked the words  first, I  could store the
  1053.              table  automatically  in    alphabetical  order    and  thus
  1054.              generating the  table would be trivial.
  1055.  
  1056.                   Almost all  the books and  articles  I  see  deal  only
  1057.              with double-linked  lists, where  there is   a pointer  to a
  1058.              previous record,  and a  pointer to a record that is next in
  1059.              line.   This  would be   overcomplicated  for   something as
  1060.              simple  as    just  generating    a  list    of  words    in
  1061.              alphabetical  order. I  didn't want  frequency  counts in  a
  1062.              binary tree, I just wanted a  list of words - and it  seemed
  1063.              trivial.
  1064.  
  1065.                   I have   used Pascal  for over 5  years and doing  this
  1066.              little exercise taught  me something about the  language and
  1067.              how  it works.  It also taught me   a little about the way I
  1068.              was thinking about certain concepts.
  1069.  
  1070.                   Every time I started on the means to store the table, I
  1071.              kept  either losing  items or  not storing the  new entries.
  1072.              The standard  method for  working with a  linked list  is to
  1073.              have a start pointer, and additionally  to have a 'traverse'
  1074.              pointer,  as described above.   You  follow  down  the links
  1075.              until you  find the entry you  want or until you run out  of
  1076.              items.
  1077.  
  1078.                   One thing I had misunderstood  was that when you have a
  1079.              second  pointer,  the  pointer  is  not  the  data,  and two
  1080.              pointers  pointing to    the same   place  are not  the same
  1081.  
  1082.  
  1083.                                                                        21
  1084.  
  1085.              thing.  This means, if you have
  1086.  
  1087.                        var
  1088.                             T,T1:Tokp;
  1089.                             name:maxstring;
  1090.  
  1091.                        begin
  1092.                             NEW(T);
  1093.                             T1 := T;
  1094.  
  1095.                   That any  change to  T1 will not have any effect on the
  1096.              system, unless you do something to one of the fields pointed
  1097.              to by t1.  Remember, just   because T and T1  point  to  the
  1098.              same  place do not  make them the  same thing.   And that is
  1099.              what caused me so much trouble.
  1100.  
  1101.                   In  the enclosed  program (WORDCOUNT.PAS)  is the  word
  1102.              count program I wrote. If you notice the section where T2 is
  1103.              allocated then the values are all moved:
  1104.  
  1105.                          IF t1^.token > tab.sym THEN
  1106.                             BEGIN
  1107.                                  new(t2);
  1108.                                  tab.nwords := tab.nwords+1;
  1109.                                  t2^.count := t1^.count;
  1110.                                  t2^.token := t1^.token;
  1111.                                  t2^.next  := t1^.next;
  1112.                                  t1^.count := 1;
  1113.                                  t1^.token := tab.sym;
  1114.                                  t1^.next  := t2;
  1115.                             END;
  1116.  
  1117.                   Merely assigning  values to   T2 would not have worked,
  1118.              because T2  is local to  that procedure.   The only   way to
  1119.              get the  values to  stick is  to use the existing values and
  1120.              attach these.
  1121.  
  1122.                   This  program sample  was  added  to  fix  two  glaring
  1123.              deficiencies:  the  lack of  an  explanation in  the  use of
  1124.              single  linked   lists,  and   one   mistake  I was  making,
  1125.              confusing  the reference pointer with the data.  My guess is
  1126.              that if I am doing this, others are also.
  1127.  
  1128.                                                                        22
  1129.  
  1130.                                     For Beginners
  1131.                                     By Bob Gowans
  1132.               
  1133.                   Having discussed important features of programming such
  1134.              as design, input and output statements in Pascal, the use of
  1135.              relevant  comments  and  programming   style  we  can   give
  1136.              ourselves  a self  congratulatory pat  on the back,   but...
  1137.              before  you  can  achieve the  ultimate  goal,  writing that
  1138.              elusive master program, complete with pop  up menus and user
  1139.              friendly screens you  must learn to master the  art of being
  1140.              selectively  repetitive in  your programming  technique. The
  1141.              computer is  really worth  it's weight in  gold when  it can
  1142.              carry out,  on our behalf,  long and boring  tasks producing
  1143.              results at  amazing speed.  For example  a payroll  program,
  1144.              used by a large company, has to calculate net pay of each of
  1145.              it's employees  - this is essentially a repetitive task. The
  1146.              same  program may  base it's  calculations  on variable  tax
  1147.              rates,  depending  on gross  pay. Thus,  the program  has to
  1148.              select  a  course of action  for certain circumstances. Lets
  1149.              take the issue of selection and repetition and treating each
  1150.              as a separate  concept briefly consider their use in program
  1151.              design.
  1152.               
  1153.              Selection
  1154.              =========
  1155.               
  1156.                   When we are faced with a problem we usually embark on a
  1157.              course of action arrived at through a mental  process called
  1158.              decision making.  Decisions are   an important  part of  our
  1159.              everyday lives, we  make countless decisions  each day   and
  1160.              branch out along different courses of action to achieve what
  1161.              we  want. From  many  different  alternatives  we  SELECT  a
  1162.              particular course of action.  IF I  get home on time tonight
  1163.              THEN  I will  watch the game  on T.V.  ELSE I will  read PNL
  1164.              might  be a  simplified way  to express  a form  of decision
  1165.              making. In terms  of program  design decision  making is  an
  1166.              important concept  and one way   to deal  with this is  very
  1167.              similar  to the human decision example given above. We would
  1168.              express this as follows :-
  1169.               
  1170.                if ( test of truth of a statement)
  1171.                then
  1172.                   carry out a set of instructions when the test is true
  1173.                else
  1174.                   carry out a set of instructions when the test is false
  1175.                ifend
  1176.               
  1177.                   For  example,  what  follows   is  a  design   language
  1178.              implementation  of a simple  selection statement which tests
  1179.              whether a person is married or  not and writes out a message
  1180.              accordingly.
  1181.  
  1182.  
  1183.                                                                        23
  1184.  
  1185.               
  1186.                   1.1 if married = true
  1187.                   1.2 then
  1188.                   1.3  write out 'congratulations'
  1189.                   1.4 else
  1190.                   1.5  write out 'keep trying'
  1191.                   1.6 ifend
  1192.              If   the   person   is   married   he   gets   the   message
  1193.              'congratulations', if not  then is presented with  the 'keep
  1194.              trying'  message. Remember  the position  of  the words  if,
  1195.              then, else and ifend and note the indentation of the actions
  1196.              to be performed.
  1197.               
  1198.               
  1199.              Repetition
  1200.              ==========
  1201.               
  1202.                   Repetitive execution of program statements involves the
  1203.              use  of loops. A conditional loop  is controlled ie. started
  1204.              or  finished, by  simple  or  complex  conditions.There  are
  1205.              several  ways in which loops  can be implemented , initially
  1206.              we   will   deal   with   a  type   that   tests   for   the
  1207.              stopping/starting condition at  the beginning of a  loop. At
  1208.              this stage we will not be dealing with unconditional loops,
  1209.              this type of loop will execute a predetermined number of
  1210.              statements, however  it is as  well that you are  aware that
  1211.              they exist. If  the loop is to be executed while a condition
  1212.              is  true, then  the loop  control is  written as  LOOP WHILE
  1213.              condition.  The loop will take the following form :-
  1214.               
  1215.              loop test   (ie. loop while condition is true.)
  1216.                 statement 1
  1217.                 statement 2
  1218.                 etc...
  1219.              loopend
  1220.               
  1221.                   It is very  important to observe  two  rules when using
  1222.              conditional  loops.  The  first rule  is  to  initialize any
  1223.              variables, prior to entering the loop, which will be updated
  1224.              within  the  loop. The  second  rule  is to  initialize  any
  1225.              variables used in the loop test ( ie. the  condition ) prior
  1226.              to entering  the loop. To illustrate the  importance of this
  1227.              lets consider the following  design which repetitively reads
  1228.              in a real number from the keyboard and sums the total of all
  1229.              the numbers entered and outputs the final total.
  1230.               
  1231.              1 initialize variables updated in the loop
  1232.              2 read in first number
  1233.              3 loop while number is positive
  1234.              4   update total
  1235.              5   read in next number
  1236.              6 loopend
  1237.  
  1238.  
  1239.                                                                        24
  1240.  
  1241.              7 write out total
  1242.               
  1243.              Note that total  is a variable that is consistently updated,
  1244.              within  the loop  and that  number is  the variable  used to
  1245.              determine the condition  of the loop ( ie.  continue or stop
  1246.              ). This information can be tabulated as follows :-
  1247.               
  1248.              Identifier     Description                    Type
  1249.              =========      ===========                    =====
  1250.               
  1251.              number         number input                   real variable
  1252.               
  1253.              total          accumulated total of
  1254.                             numbers input                  real variable
  1255.               
  1256.              Following the top-down methodology lets individually  refine
  1257.              the steps given above.
  1258.               
  1259.              Steps 2,4,5 and 7 are easy :-
  1260.               
  1261.              2.1 read in number
  1262.               
  1263.              4.1 set total to total + number
  1264.               
  1265.              5.1 read in number
  1266.               
  1267.              7.1 write out 'The total sum of all the numbers is ',total.
  1268.               
  1269.              Lets not forget to include relevant input prompts. Steps 2.1
  1270.              and 5.1 will require further refinement.
  1271.               
  1272.              2.1 write out 'Enter any positive number (negative number to
  1273.              quit)'
  1274.              2.2 read in number
  1275.               
  1276.              5.1 write out 'Enter any positive number (negative number to
  1277.              end)'
  1278.              5.2 read in number
  1279.               
  1280.               
  1281.                   The two  steps that read  in number at 2.2  and 5.2 are
  1282.              required because the initial condition of the loop at step 3
  1283.              depends  on the value of  number read in  at step 2.2  -  we
  1284.              have thus  met the  requirement of loop  rule #2  by setting
  1285.              number to it's initial value. Once the loop has been entered
  1286.              control  passes through steps  4.1,5.1,5.2 until at  step 6,
  1287.              control passes back to step 3. The condition of the  loop is
  1288.              tested again and  it's execution depends on the data entered
  1289.              at step  5.2. The two  input statements are necessary  - the
  1290.              first to test  the loop initially and the  second to provide
  1291.              subsequent test of the loop condition.
  1292.            
  1293.  
  1294.                                                                        25
  1295.  
  1296.                   Refining  step  three  requires  us  to  see  that  the
  1297.              condition  is true  as long  as  number is  positive. So  if
  1298.              number is  entered as  a negative  the loop will  terminate.
  1299.              This is a  simple condition and can be  expressed as follows
  1300.              :-
  1301.               
  1302.              3.1 loop while number >= 0
  1303.               
  1304.                   If  you are unsure  what the condition  operators mean,
  1305.              refer to  the table under  the section IMPLEMENTATION  OF IF
  1306.              THEN ELSE which is further on in the article.
  1307.               
  1308.                   The  stopping data  item (  ie a  negative number  ) is
  1309.              known  as a  SENTINEL VALUE.  If the  number variable  has a
  1310.              negative value the  loop condition is not true  and the loop
  1311.              is not executed. In this case  the execution of the loop  is
  1312.              controlled by user input.
  1313.               
  1314.                   To  further  refine  step  1  we  require  to know  the
  1315.              variables that will  be updated in the loop.  Both total and
  1316.              number are updated within the loop but only total is updated
  1317.              by assignment ( number is updated as being input ), so total
  1318.              requires  to be initialized  before being used  in the loop.
  1319.              This would necessitate  setting total to zero.  The complete
  1320.              design is given below :
  1321.               
  1322.              1.1 set total to 0
  1323.              2.1 write out 'Enter any positive number (negative number to
  1324.              quit)'
  1325.              2.2 read in number
  1326.              3.1 loop while number >= 0
  1327.              4.1    set total to total + number
  1328.              5.1       write  out 'Enter  any  positive number  (negative
  1329.              quits)'
  1330.              5.2    read in number
  1331.              6   loopend
  1332.              7.1 write out 'The total sum of all the numbers is ',total.
  1333.               
  1334.                   We have dealt, briefly with a method of selection and a
  1335.              method  of  repetition and  program  language  methods which
  1336.              allow these concepts  are called CONTROL STRUCTURES.  As you
  1337.              guessed there are other control structures but we will leave
  1338.              those for another  article. Lets go on to  implement the two
  1339.              control structures we have discussed in Pascal.
  1340.               
  1341.               
  1342.              IMPLEMENTATION OF IF THEN ELSE
  1343.              ==============================
  1344.               
  1345.                   The if statements of the design are written, in Pascal,
  1346.              similarly  except you  do  not  need  to include  the  ifend
  1347.              statement.
  1348.  
  1349.  
  1350.  
  1351.                                                                        26
  1352.  
  1353.               
  1354.              if condition
  1355.              then
  1356.                 begin
  1357.                     statement 1;
  1358.                     statement 2;
  1359.                     ........ etc
  1360.                 end
  1361.              else
  1362.                 begin
  1363.                    statement 1;
  1364.                    statement 2;
  1365.                    ......... etc
  1366.                 end;
  1367.               
  1368.                   Note that  the Pascal reserved words BEGIN and END mark
  1369.              the start  and finish  of multiple  statements. If  there is
  1370.              only one statement to be executed then the BEGIN and END may
  1371.              be excluded. Lets discuss the  implementation of  our design
  1372.              concerning the married or single survey. I have added to the
  1373.              basic design  by  stipulating an  interactive  program  that
  1374.              prompts  the user to respond 'y' or  'n' to a question. This
  1375.              introduces us  to  the data  structure CHAR.  The data  type
  1376.              char, provided by Pascal, enables us to manipulate character
  1377.              sets including  upper-case  letters,  the  digits  and  some
  1378.              punctuation marks and  mathematical symbols.  When the  user
  1379.              inputs a  character -  in this case  either 'y' or  'n', the
  1380.              character input is  assigned to the char  variable RESPONSE.
  1381.              By using  the if...  then... else...  control structure  the
  1382.              program   determines  what   the   user  input;   the  users
  1383.              response.If it is 'y' then the a message is output, if it is
  1384.              'n'  then a different  message is  output. Please  note that
  1385.              when  testing  for  characters they  should  be  included in
  1386.              single  quotation  marks.  When  inputting  characters  they
  1387.              should be written as they are - without quotation marks.
  1388.               
  1389.              program ismarried;
  1390.               
  1391.              var
  1392.               
  1393.                 response : char;
  1394.               
  1395.              begin
  1396.                write('Are you married ( enter y or n ) > ');
  1397.                read(response);
  1398.                if response = 'y' {Condition test. Note
  1399.                                   test for character uses ''}
  1400.                   then
  1401.                      writeln('You lucky person')
  1402.                   else
  1403.                      writeln('What''s your phone number?'); {Ifend}
  1404.                   writeln;
  1405.                                                                        27
  1406.  
  1407.              end.
  1408.               
  1409.                   A  condition is  a test  which  is carried  out on  the
  1410.              values of  variables to  compare them in  some way.  As your
  1411.              knowledge  of  Pascal  evolves their  use  will  become more
  1412.              apparent to you.  For now lets  summarize the various  tests
  1413.              for conditions in a table.  
  1414.  
  1415.              Operator                         Condition
  1416.              ========                         =========
  1417.               
  1418.               >                               is greater than
  1419.               <                               is less than
  1420.               =                               is equal to
  1421.               <>                              is not equal to
  1422.               >=                              is greater than or equal to
  1423.               <=                              is less than or equal to
  1424.               
  1425.                   You can probably  see, that comparison operators  are a
  1426.              powerful programming  tool that  can be used  to test  for a
  1427.              variety of  conditions.  Now try  the  following  exercises.
  1428.              Solutions will be given at the end of the article.
  1429.               
  1430.               
  1431.              Ex1
  1432.              ____________________________________________________________
  1433.               
  1434.                   Devise a  design to read  in two numbers,  compare them
  1435.              and print out the two numbers in ascending order.
  1436.               
  1437.               
  1438.              Ex2
  1439.               
  1440.               
  1441.                   Length, width  and  height are  integer  variables  and
  1442.              woman,  man  and  child are  char  variables.  Which of  the
  1443.              following are valid conditions?
  1444.  
  1445.              Solutions are given at end of article.
  1446.               
  1447.              (a) length > 24
  1448.              (b) woman = 'Wendy'
  1449.              (c) child = 5
  1450.              (d) height = 63
  1451.              (e) man >= 70
  1452.              (f) width = '6'
  1453.              (g) child = 'C'
  1454.  
  1455.  
  1456.                                                                        28
  1457.  
  1458.              IMPLEMENTATION OF THE WHILE DO LOOP
  1459.              ===================================
  1460.               
  1461.                   While loops are implemented in Pascal as given below
  1462.               
  1463.              while condition do 
  1464.                   begin
  1465.                      statement1;
  1466.                      statement2;
  1467.                      .........etc
  1468.                   end;
  1469.               
  1470.                   The statements  to be executed repeatedly are separated
  1471.              by semicolons and if there  is only one statement within the
  1472.              loop  the keywords BEGIN and END may be exclude. Now lets go
  1473.              back  to  our  design from  the  REPETITION  section  in the
  1474.              article and implement this in Pascal.
  1475.               
  1476.              program addup;
  1477.              { Adds up  and prints total, to the  screen, of real numbers
  1478.              input by the user }
  1479.              var
  1480.                 total,number : real;
  1481.               
  1482.              begin
  1483.                 total := 0; {Initialize variables updated in loop}
  1484.                 write('Enter a  positive number (negative number to exit)
  1485.              > ');
  1486.                 readln(number);
  1487.                 while number >= 0 do { start of loop }
  1488.                    begin
  1489.                      total := total + number;
  1490.                      writeln;
  1491.                      write('Enter a positive # (neg. # to exit) > ');
  1492.                      readln(number)
  1493.                    end;{ of while do loop }
  1494.                 writeln;
  1495.                 writeln('The total sum of numbers entered is ',total:5:2)
  1496.              end.
  1497.               
  1498.                   As you can see the actual implementation  of the design
  1499.              into Pascal was  fairly straightforward, the brain  work was
  1500.              required at the design stage.  So while you are in  the mood
  1501.              try out the following exercise :-
  1502.               
  1503.              Ex3
  1504.               
  1505.               
  1506.                   Design a program  that will read in the ages of all the
  1507.              participants,  the program will  keep a  count of  the total
  1508.              amount of users and will print out  the maximum age plus the
  1509.              total amount of users. Hint - do not forget the sentinel.
  1510.  
  1511.                                                                        29
  1512.  
  1513.               
  1514.                   Before  I give the solutions to the exercises I thought
  1515.              I would include this useful Turbo Pascal routine that checks
  1516.              the amount  of space available  on a default hard  disk. The
  1517.              routine is  not really aimed  at beginners but gives  you an
  1518.              insight into the power of Turbo Pascal and it's control over
  1519.              DOS. To more experienced users, feel free to modify the code
  1520.              to suit your own needs.
  1521.               
  1522.              program HDcheck;
  1523.               
  1524.              uses crt,dos;
  1525.               
  1526.              var
  1527.                i : integer;
  1528.                totalspace,usedspace,freespace : real;
  1529.               
  1530.              begin
  1531.                 clrscr;
  1532.                 writeln;
  1533.                 totalspace := disksize(0)/1000000;
  1534.                 writeln('Total disk space = ',totalspace:5:2,' MBytes');
  1535.                 writeln;
  1536.                 usedspace := (disksize(0) - diskfree(0))/1000000;
  1537.                 writeln('Disk space used  = ',usedspace:5:2,' MBytes');
  1538.                 writeln;
  1539.                 freespace := diskfree(0)/1000000;
  1540.                 writeln('Space free       = ',freespace:5:2,' MBytes');
  1541.                 for i := 1 to 15 do
  1542.                 writeln;
  1543.                 writeln('HDCheck by B.Gowans');
  1544.                 writeln;
  1545.                 writeln('Press enter to continue');
  1546.                 readln;
  1547.                 clrscr
  1548.              end.
  1549.               
  1550.                   The use of control  statements such as IF...THEN...ELSE
  1551.              and WHILE DO will greatly enhance your programming abilities
  1552.              and  this  is  just  the start  of  the  control  structures
  1553.              available  to  Pascal.  Practice using  these  structures by
  1554.              following  the  examples found  in  the text  books  and get
  1555.              comfortable in using them. Here are the solutions to the
  1556.              exercises
  1557.               
  1558.              Ex1 :
  1559.               
  1560.              1 initialize variables
  1561.              2 compare the numbers
  1562.              3 write out numbers in order
  1563.               
  1564.              1.1 read in number1
  1565.  
  1566.  
  1567.                                                                        30
  1568.  
  1569.              1.2 read in number2
  1570.              2.1 if number1 > number2
  1571.              2.2 then
  1572.              2.3   write out number1
  1573.              2.4   write out number2
  1574.              2.5 else
  1575.              2.6   write out number2
  1576.              2.7   write out number1
  1577.              2.8 ifend
  1578.               
  1579.               
  1580.               
  1581.              Ex2 :
  1582.               
  1583.              (a) valid
  1584.              (b) invalid - variable is of type char and not string.
  1585.              (c) invalid - variable is of type char and not integer.
  1586.              (d) valid
  1587.              (e) invalid - for same reasons as (c).
  1588.              (f) invalid - width is integer variable and not char.
  1589.              (g) valid.
  1590.               
  1591.              Ex3 :
  1592.               
  1593.              1. initialize variables
  1594.              2. loop while users to be processed
  1595.              3.   process age
  1596.              4.   process count
  1597.              5. loopend
  1598.              6. write out count, maxage
  1599.               
  1600.              Further refinement :-
  1601.               
  1602.                 1.1  set count to 0
  1603.                 1.2  set max to 0
  1604.               1.3.1  write out 'Please enter age ( enter -1 to quit )'
  1605.               1.3.2  read in age
  1606.                 2.1  loop while age < > -1
  1607.                 3.1     if age > max
  1608.                 3.2     then
  1609.                 3.3        set max to age
  1610.                 3.4     else
  1611.                 3.5        { do nothing }
  1612.                 3.6     ifend
  1613.                 4.1     set count to count + 1
  1614.                 4.2     write out 'Please enter age ( enter -1 to quit )'
  1615.                 4.3     read in age
  1616.                   5     loopend
  1617.                 6.1     write out 'The maximum age was ',maxage
  1618.                 6.2     write out 'Out of a total of ',count,' people.'
  1619.               
  1620.              The implementation in Pascal follows - please note there may
  1621.  
  1622.                                                                        31
  1623.  
  1624.              be small  changes in the  implementation which does  not affect
  1625.              the overall design.
  1626.               
  1627.              program age_survey;
  1628.               
  1629.              var
  1630.               
  1631.              age : integer;
  1632.              maxage : integer;
  1633.              count : integer;
  1634.               
  1635.              begin
  1636.                 write('Enter age to nearest year ( -1 to quit ) > ');
  1637.                 readln(age);
  1638.                 count :=  0;
  1639.                 maxage := 0;
  1640.                 while age <> -1 do { start loop, stop with age = -1 }
  1641.                    begin
  1642.                      if age > maxage { if start }
  1643.                      then
  1644.                         maxage := age
  1645.                      else
  1646.                { do nothing };{no other branching is necessary so ifend}
  1647.                      count := count + 1;
  1648.                      writeln;
  1649.                      write('Enter age to nearest year (-1 to quit ) > ');
  1650.                      readln(age)
  1651.                    end;
  1652.                    writeln;
  1653.                    writeln('The greatest age was ',maxage,' years');
  1654.                    writeln;
  1655.                    writeln('The total number surveyed was ',count)
  1656.              end.
  1657.               
  1658.                   All  the code  in  this article  has  been written  and
  1659.              compiled  using Turbo Pascal v4. The executable code was run
  1660.              on an Opus  PC 5 under DOS  3.3. There is no  guarantee that
  1661.              the  same   code  will   run  under   your  own   particular
  1662.              configuration.
  1663.  
  1664.                                                                        32
  1665.  
  1666.                                   Recursion is Easy
  1667.                                     By Chris Burke
  1668.  
  1669.                   Recursion and pointers seem to be the two subjects that
  1670.              cause beginners  in pascal  the most  heartache. This  brief
  1671.              article aims to delve into the subject of recursion.
  1672.  
  1673.              Introduction
  1674.  
  1675.                   Imagine you (Alfred) are talking to Bob, when Christine
  1676.              walks  up and rudely  interrupts and starts  talking to you.
  1677.              You put  up with it and  talk to Christine (she  is prettier
  1678.              than  Bob anyway).  While  talking  to  Christine,  her  mum
  1679.              (Daphne) wants  a bit of a chat -  you being the wise person
  1680.              you are  (and liking  Christine so much)  decide to  talk to
  1681.              Daphne,  just  after  finishing  your  chat  and  commencing
  1682.              conversing  with Christine, the telephone rings - you answer
  1683.              and  (OH  NO!!) it  is Elaine  wanting to  go to  the movies
  1684.              tonight, you quickly say sure no problems see you  at 8, see
  1685.              you then,  bye and  continue talking to  Christine. After  a
  1686.              little while  Christine leaves  and you  restart talking  to
  1687.              Bob.
  1688.  
  1689.              So, What have you been doing - well
  1690.              1. You have been two-timing, and deserve all you get.
  1691.              2. You have been using your 'Talk' function recursively.
  1692.  
  1693.              i.e.
  1694.                Talk(Bob)
  1695.                 Talk(Christine)
  1696.                  Talk(Daphne)
  1697.                 Return to Talk(Christine)
  1698.                  Talk(Elaine)
  1699.                 Return to Talk(Christine)
  1700.                Return to Talk(Bob)
  1701.  
  1702.                   So now that you understand  a bit about the concepts of
  1703.              recursion  lets go onto  more computer oriented  problems of
  1704.              recursion. 
  1705.  
  1706.                   One  of the most  common examples  of recursion  is the
  1707.              factorial program -  as it gets quoted so  often I shall use
  1708.              the  example here.  For  those  not  familiar  with  what  a
  1709.              factorial is - here is an explanation :
  1710.  
  1711.                   The  factorial  of  a  positive  number  (0,1,2...)  is
  1712.              defined as follows :
  1713.  
  1714.                factorial of N = N*(N-1)*(N-2)....*1
  1715.                factorial  of 0  = 1  (by definition  - i.e.  for no  real
  1716.              reason)
  1717.  
  1718.  
  1719.                                                                        33
  1720.  
  1721.              (For  those with  a  little curiosity,  there  is a  related
  1722.              function called the  gamma function which works  on negative
  1723.              numbers and non-integers.)
  1724.  
  1725.              The factorial is represented using the ! symbol
  1726.  
  1727.                i.e. 12! represents the factorial of 12
  1728.  
  1729.                   The first way the programmer would  go about defining a
  1730.              function to calculate the factorial is as follows :
  1731.  
  1732.                function factorial(N:longint):longint;
  1733.                var
  1734.                 Count,Temp:longint;
  1735.                begin
  1736.                 Temp:=1;
  1737.                 for Count:=1 to N do
  1738.                   Temp:=Temp*Count;
  1739.                 Factorial:=Temp;
  1740.                end;
  1741.  
  1742.              which would in effect for N=5 calculate the following
  1743.  
  1744.                  factorial(N) = 1*2*3*4*5
  1745.  
  1746.              which adheres to the formula above.
  1747.  
  1748.  
  1749.              The Quantum Leap
  1750.  
  1751.                   The  quantum leap  in thought  is to  realize that  the
  1752.              above formula:
  1753.  
  1754.                 N!=N*(N-1)*(N-2)*(N-3)...*1 can be written differently.
  1755.  
  1756.              Lets take an example, say 5!.
  1757.  
  1758.                 5!=5*(5-1)*(5-2)*(5-3)*(5-4)
  1759.  
  1760.              or    =5*   4  *   3  *   2  *   1   BUT LOOK!! this  can be
  1761.              written
  1762.  
  1763.                   =5*   4!
  1764.              and
  1765.                 4!=4*3*2*1 = 4*3!    AND SO ON.....
  1766.  
  1767.              which means the original formula can be written as
  1768.  
  1769.                 N!=N*(N-1)!   -  This is the mathematical equivalent of
  1770.                                  recursion.
  1771.  
  1772.              converting this to pascal is a fairly simple step :
  1773.  
  1774.                                                                        34
  1775.  
  1776.              function factorial(N:longint):longint;
  1777.              begin
  1778.                factorial:=N*factorial(N-1)
  1779.              end;
  1780.  
  1781.              EASY - just a straight implementation in pascal....
  1782.  
  1783.                   The only thing left to do is to implement what is known
  1784.              as  an  exit condition  - or  a termination  condition, this
  1785.              tells  the above  factorial  function when  to stop  what is
  1786.              currently an infinite loop, the easiest way to do this is to
  1787.              realize that factorial(0)=1  as defined by our  mathematical
  1788.              gurus. The modified code is :
  1789.  
  1790.              function factorial(N:longint):longint;
  1791.              begin
  1792.                if N=0 then factorial:=1
  1793.                       else factorial:=N*factorial(N-1)
  1794.              end;
  1795.  
  1796.                   This  is where the IDE  environment in the turbo pascal
  1797.              compiler  comes  in  handy.  Write  a  little  program  that
  1798.              includes the above function as follows :
  1799.  
  1800.              program TestRecursion;
  1801.              function factorial(N:longint):longint;
  1802.              begin
  1803.                if N=0 then factorial:=1
  1804.                       else factorial:=N*factorial(N-1)
  1805.              end;
  1806.              begin
  1807.               writeln('Factorial 5=',factorial(5));
  1808.               writeln('Factorial 0=',factorial(0));
  1809.              end.
  1810.  
  1811.                   Try  tracing through this  code remembering to  use the
  1812.              'step  over' on the 'begin'  and the 'step  into' on the two
  1813.              writeln  statements.  After  a little  playing  and  placing
  1814.              watches on N.  (Don't forget  to put Local Symbols and Debug
  1815.              Information on in  the options). By now  recursion should be
  1816.              somewhat more obvious.
  1817.  
  1818.              Something A Little More Useful
  1819.  
  1820.                   This subject may be of a little more interest, but as I
  1821.              have  always found -  the best way of  learning is by doing,
  1822.              and when you have it working you will be far more satisfied.
  1823.  
  1824.                   The following  hints should  get you on  your way  to a
  1825.              routine  which does some  function MYFUNC  on every  file on
  1826.              your hard disk - in every directory on your hard drive.
  1827.  
  1828.                                                                        35
  1829.  
  1830.              In english here is what you would do :
  1831.  
  1832.              1.  Write a  routine which does  MYFUNC on  every file  in a
  1833.              specified
  1834.              directory something like the following :
  1835.  
  1836.                 procedure DoMyFuncHere(D:Pathstring);
  1837.                 var
  1838.                  F:FileString;
  1839.                 begin
  1840.                  F:=GetFirstName; (* Remember : *)
  1841.                  while F is valid do (* we want all directories
  1842.                                         and files               *)
  1843.                  begin
  1844.                    MYFUNC(D+F);
  1845.                    F:=GetNextName;
  1846.                  end;
  1847.                 end;
  1848.  
  1849.               test this procedure out and see if it works - OK
  1850.  
  1851.              2. Modify this  routine so that it  calls itself recursively
  1852.              when there is a subdirectory  (remember - don't get  worried
  1853.              by the fact that the routine is calling itself)
  1854.  
  1855.                { Ed. Note: Semi-Pascal algorithm }
  1856.  
  1857.              |   procedure DoMyFuncHere(D:Pathstring);
  1858.              |   var
  1859.              |    F:FileString;
  1860.              |
  1861.              |   begin
  1862.              |    F:=GetFirstName; (* Remember : *)
  1863.              |     while F  is valid do   (* we want all  directories and
  1864.              files *)
  1865.              |    begin
  1866.              |      if (F='.') or (F='..') then
  1867.              |                                                           
  1868.              DontGoHereThereIsProblemsIfYouDo;
  1869.              |      else if F_IsADirectory then
  1870.              |                            DoMyFuncHere(D+F)
  1871.              |      else MYFUNC(D+F);
  1872.              |      F:=GetNextName;
  1873.              |    end;
  1874.              |   end;
  1875.  
  1876.                { Ed. Note: Actual Pascal algorithm }
  1877.              ~program test;
  1878.              ~uses crt,dos;
  1879.              ~
  1880.              ~  Procedure MyFunc (FileRec : SearchRec);
  1881.              ~  begin
  1882.              ~        Writeln(FileRec.Name);
  1883.              ~  end;
  1884.              ~
  1885.                                                                        36
  1886.  
  1887.              ~  procedure DoMyFuncHere(D:Pathstr);
  1888.              ~  var
  1889.              ~  SR : SearchRec;
  1890.              ~
  1891.              ~  begin
  1892.              ~    FindFirst(D+'*.*',Directory+Archive,SR);
  1893.              ~    while DosError = 0 do
  1894.              ~    begin
  1895.              ~      if (SR.Name <> '.') AND (SR.Name <> '..') then
  1896.              ~        If (SR.Attr AND Directory) > 0 then
  1897.              ~          DoMyFuncHere(SR)
  1898.              ~        else
  1899.              ~          MYFUNC(D+SR.NAME);
  1900.              ~      FindNext(SR);
  1901.              ~    end;
  1902.              ~  end;
  1903.              ~
  1904.              ~begin
  1905.              ~  DoMyFuncHere('C:\');
  1906.              ~end.
  1907.  
  1908.              Try this out by calling DoMyFuncHere('C:\');
  1909.              I  am sure you can put your  imagination to other  uses for
  1910.              such a recursive directory engine, ie: finding and deleting
  1911.              ALL  BAK  files  on a drive,   or  counting  the  size   of
  1912.              subdirectories, you can modify the search criterion in  the
  1913.              FINDFIRST line.
  1914.  
  1915.              A BIT OF EXPLAINING
  1916.              ------------------
  1917.              Imagine a simple directory like this,
  1918.  
  1919.                COMMAND.COM     1 calls MYFUNC
  1920.                AUTOEXEC.BAT    1 calls MYFUNC
  1921.                <DOS>           1 calls DoMyFuncHere - recursively
  1922.                  <.>            2 skips
  1923.                  <..>           2 skips
  1924.                  FDISK.COM      2 calls MYFUNC
  1925.                  DEBUG.COM      2 calls MYFUNC
  1926.                                 2 returns from second level
  1927.                CONFIG.SYS      1 calls MYFUNC
  1928.                <UTILS>         1 calls DoMyFuncHere - recursively
  1929.                  <.>            2 skips
  1930.                  <..>           2 skips
  1931.                  LIST.COM       2 calls MYFUNC
  1932.                  <NU>           2 calls DoMyFuncHere - recursively
  1933.                    <.>           3 skips
  1934.                    <..>          3 skips
  1935.                    SI.EXE        3 calls MYFUNC
  1936.                                  3 returns from third level
  1937.                                                                        37
  1938.  
  1939.                  4EDIT.EXE      2 calls MYFUNC
  1940.                                 2 returns from second level
  1941.                4DOS.COM        1 calls MYFUNC
  1942.                                1 returns and exits to main program
  1943.  
  1944.                   By  following the above (the number represents how deep
  1945.              you have gone)  you should  be able  to see  how simple  the
  1946.              program to look at every file on your hard disk is.
  1947.  
  1948.              If you want any more assistance on recursion see the section
  1949.              above called 'A BIT OF EXPLAINING' otherwise continue to the
  1950.              conclusion.
  1951.  
  1952.              Conclusion
  1953.  
  1954.                   I hope that  this description of recursion  will answer
  1955.              your questions on  recursion, if you have  any questions for
  1956.              me then I have a point called 'Mindware' fidonet 3:640/305.1
  1957.  
  1958.                                                      Christopher Burke
  1959.                                                      Brisbane, Queensland
  1960.                                                      AUSTRALIA
  1961.  
  1962.  
  1963.                   Chris Burke is owner/operator of a contract Programming
  1964.              company called Mindware in Brisbane, Australia.  He programs
  1965.              commercially using various languages  including Turbo Pascal
  1966.              from  version 2.0 through to version 5.5 professional (Using
  1967.              Object Professional), Assembler, and Clarion.
  1968.                   He runs a point Fidonet system, and can be contacted at
  1969.              3:640/305.1.
  1970.  
  1971.  
  1972.                                                                          38
  1973.  
  1974.                                       Conclusion
  1975.  
  1976.                There  are a  couple things  I'd  like to  point about  some
  1977.           future issues.  Bob Gowans will,  of course, continue  to produce
  1978.           his column, which has become incredibly popular. Richard is going
  1979.           to give us quite bit of stuff on graphics in Pascal, so that will
  1980.           also  be a  regular contribution.  I  will be  starting a  series
  1981.           pretty soon  on doing large  projects. I am  just finishing  up a
  1982.           large project that  involved 5 other programmers and  quite a bit
  1983.           of design work before the  implementation. I'd like to go  over a
  1984.           lot  of the stuff we did. This  alone should take several issues,
  1985.           but I  think you will find  it very interesting. The  code alone,
  1986.           because it is  so vast, will be broken up into several issues and
  1987.           each unit will be covered alone and then the final integration of
  1988.           the entire project will be examined.
  1989.  
  1990.                I feel bad  that I can't seem  to get the newsletter  out as
  1991.           often as I  would like, but  like many of you,  I have to  set my
  1992.           priorities, one  of them, earning  a living.  Hopefully you  will
  1993.           forgive me  for this. All I can do is  make a promise that I will
  1994.           try my best to get each issue out as soon as possible. 
  1995.  
  1996.                I would also like  to ask, as I do in  every issue, that you
  1997.           try  to find the  time to send  in some of  your own material for
  1998.           inclusion in the  newsletter. Without user contributions,  I just
  1999.           can't  keep this going. They  have been good  lately, but I could
  2000.           handle  a  few  more.  So,  please, if  you  don't  feel  you can
  2001.           contribute, try to find friends that can. Try to get them to send
  2002.           in stuff they've done.
  2003.  
  2004.                One last word  on the distribution list. I  keep quite a bit
  2005.           of the updates in  a directory which I search  at the end of  the
  2006.           month to make updates to the distribution list. Several days ago,
  2007.           because of a strange problem, that directory, almost exclusively,
  2008.           was  completely  wiped  out.  I  have been  unable  to  make  any
  2009.           corrections  to  the  distribution   list.  If  you  sent   in  a
  2010.           correction, or addition, please send me the information  again so
  2011.           that  I   can  make   those  corrections.  I'm   sorry  for   any
  2012.           inconvenience this may have caused.
  2013.  
  2014.                Ah,  and  one final  thing  that  I  almost forgot.  I  have
  2015.           recently put a second computer  together. This should help me put
  2016.           a little more  time into the newsletter, as I won't have to worry
  2017.           about bringing  my BBS  down every  time I  want to  work on  the
  2018.           newsletter. 
  2019.  
  2020.                Well, enjoy the holidays and hopefully I'll have a brand new
  2021.           issue out in early January.
  2022.                                   
  2023.                                                    _Pete Davis
  2024.  
  2025.  
  2026.                                                                          39
  2027.  
  2028.  
  2029.                The  Pascal   NewsLetter  is  Copyrighted   by  Pete  Davis.
  2030.           Articles submitted by others are  the property of the authors and
  2031.           are  used with  permission. They  may not  be treated  separately
  2032.           from this  newsletter without  the author's  permission and  thus
  2033.           maintain all distribution rules of  the newsletter as a whole. It
  2034.           may be  freely distributed  in un-modified   form, but  no charge
  2035.           whatsoever may be incurred on the recipient. All code is provided
  2036.           'as-is' with no guarantees whatsoever.
  2037.  
  2038.                The   Pascal   NewsLetter    can   be   obtained   from  the
  2039.           following locations:
  2040.  
  2041.                          GEnie : General Electric Network for Information  
  2042.                                  Exchange. It is located in the IBMPC 
  2043.                                  filelist.
  2044.  
  2045.                         Simtel : Internet address: 26.2.0.74 or            
  2046.                                  Simtel20.ARPA It is located in the        
  2047.                                  <MSDOS.PASCAL> directory.
  2048.  
  2049.             Programmer's Forum : This is the home of the PNL.              
  2050.                                  Each issue can be found in                
  2051.                                  the MAG directory from the main area.
  2052.                                  The number is on the title page.
  2053.  
  2054.                If   you  would  like  to   receive  back   issues   of  PNL
  2055.           directly  from  me,  send  a  diskette  and  $2.00  for shipping.
  2056.           Don't forget to include your address.
  2057.  
  2058.                          Send your order to:
  2059.                             Peter Davis
  2060.                             4851 Brandywine St. NW
  2061.                             Washington, DC   20016
  2062.  
  2063.                If you  are   a SysOp that   will regularly  carry PNL   and
  2064.           would like  to  have  your bulletin board  listed as such,  here,
  2065.           send  me  a  message either  by  postal  mail or  at  one  of the
  2066.           electronic  addresses  given   on  the  title   page,  with  your
  2067.           bulletin board's name, phone number, and your name.
  2068.  
  2069.                                                                          40
  2070.  
  2071.                                   Distribution List
  2072.  
  2073.                The following  is the phone numbers to bulletin boards known
  2074.           to carry  PNL. If you would  like your bulletin board's  name and
  2075.           number added  to  or deleted  from this  list, please  send me  a
  2076.           message at one of my many addresses. I can not guarantee whether 
  2077.           a listed board will have any particular issue.
  2078.  
  2079.              The Programmer's Forum ................. Phone: (202) 966-3647
  2080.                    The Programmer's Forum is the home of the PNL.
  2081.  
  2082.           BBS                       | FidoNet Addrs        |  Phone #
  2083.           --------------------------+----------------------+---------------
  2084.           The Bored                 | 1:397/3              | (512) 303-0471
  2085.           Classic City BBS          | 1:370/10             | (404) 548-0726
  2086.           Thieve's World BBS        | 1:106/805            | (713) 463-8053
  2087.           Hippocampus BBS           | 1:141/205            | (203) 484-4621
  2088.           Rogers State College      | 1:170/708            | (918) 341-8982
  2089.           The Foxtrot BBS           | 1:272/26             | (914) 567-1814
  2090.           Turbo City BBS            | 1:208/2              | (209) 599-7435
  2091.           Austin IEMUG/MIDI BBS     | 1:382/14             | (512) 258-0626
  2092.           Laser Publishers          | 1:170/403            | (918) 438-2749
  2093.           Fargo RBBS-PC             | 1:10/8               | (701) 293-5973
  2094.           Momentary Lapse of Reason |                      | (704) 327-6361
  2095.           The Demon's Den           |                      | (508) 433-2702
  2096.           The Cannibal Cafe         |                      | (508) 840-6589
  2097.           IBM Tech FIDO             |                      | (508) 433-6491
  2098.           The User Friendly BBS     |                      | (704) 323-8223
  2099.           The Disseminator BBS      | 3:640/378            | 61-7-368-1239
  2100.           Beyound Fronttiers BBS    | 2:230/101            | (+45)8694-1609
  2101.           Collision Theory          |                      | (703) 503-9441
  2102.           Merlin's Mailbox          | 2:245/39             |
  2103.           Ed-Net9600                | 1:153/734            | (604) 732-8877
  2104.  
  2105.  
  2106.  
  2107.  
  2108.  
  2109.  
  2110.  
  2111.  
  2112.  
  2113.  
  2114.  
  2115.  
  2116.  
  2117.  
  2118.  
  2119.  
  2120.  
  2121.  
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128.  
  2129.